﻿using Base.Api.Models;
using Base.Api.Repository;
using Base.Data.Entity;
using Common.AspNetCore;
using Common.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Base.Api.Service
{
    public class AuthService : CommonService
    {
        private readonly BaseRepository baseRepository;

        public AuthService(IServiceProvider provider, BaseRepository baseRep) : base(provider)
        {
            this.baseRepository = baseRep;
        }

        public async Task<MemberAuthModel> GetMemberAuthAsync(string memberId, int clientType)
        {
            var m = await GetRoleAuthByMemberIdAsync(memberId);
            if (m != null)
            {
                var roleIds = m.Roles.Select(t => t.RoleId).ToList();
                var roles = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_role>(roleIds);
                m.Roles = m.Roles.Where(t => roles.Any(t1 => t1.id == t.RoleId && t1.platform_type == clientType)).ToList();
            }

            return m;
        }

        public async Task<int> GetMemberRoleTypeAsync(string memberId, int clientType)
        {
            var m = await GetRoleAuthByMemberIdAsync(memberId);
            if (m != null)
            {
                var roleIds = m.Roles.Select(t => t.RoleId).ToList();
                var roles = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_role>(roleIds);
                if (roles.Any(t => t.platform_type == clientType && t.role_type == 1))
                {
                    return 1;
                }
            }

            return 0;
        }

        public async Task<MemberAuthModel> GetRoleAuthByMemberIdAsync(string memberId)
        {
            if (string.IsNullOrEmpty(memberId))
            {
                return null;
            }

            List<string> re = new List<string>
            {
                memberId
            };
            var r = await GetRoleAuthByMemberIdsAsync(re);
            return r != null && r.Any() ? r[0] : null;
        }

        public async Task<MemberAuthInfoModel> GetMemberAuthInfoModelAsync(List<string> memberIds)
        {
            MemberAuthInfoModel ret = new MemberAuthInfoModel
            {
                MemberRoles = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_member_auth_role>(t => memberIds.Contains(t.member_id)),
                MemberRoleGroups = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_member_auth_role_group>(t => memberIds.Contains(t.member_id)),
                Members = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_member>(memberIds),
            };
            var roleIds = ret.MemberRoles.Select(t => t.role_id).ToList();
            List<t_role_group_auth_role> roleGroupRoles = null;
            if (ret.MemberRoleGroups.Any())
            {
                var roleGroupIds = ret.MemberRoleGroups.Select(t => t.role_group_id).ToList();
                roleGroupRoles = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_role_group_auth_role>(t => memberIds.Contains(t.role_group_id));
                if (roleGroupRoles != null && roleGroupRoles.Any())
                {
                    roleIds.AddRange(roleGroupRoles.Select(t => t.role_id).ToList());
                }
            }

            roleIds = roleIds.Distinct().ToList();
            if (!roleIds.Any())
            {
                return ret;
            }

            ret.RoleAuthForms = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_role_auth_form>(t => roleIds.Contains(t.role_id));
            var roleAuthFormIds = ret.RoleAuthForms.Select(t => t.id).ToList(); 
            ret.RoleAuthFormBtns = roleAuthFormIds != null && roleAuthFormIds.Any() ?
                    await this.baseRepository.CommonRepository.GetEntitiesAsync<t_role_auth_form_btn>(t => roleAuthFormIds.Contains(t.role_auth_form_id)) :
                    new List<t_role_auth_form_btn>(); 
            ret.RoleAuthFormFields = roleAuthFormIds != null && roleAuthFormIds.Any() ?
                await this.baseRepository.CommonRepository.GetEntitiesAsync<t_role_auth_form_field>(t => roleAuthFormIds.Contains(t.role_auth_form_id)) :
                new List<t_role_auth_form_field>(); 
            ret.RoleAuthInfos = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_role_auth_info>(t => roleIds.Contains(t.role_id));
            ret.RoleGroupRoles = roleGroupRoles;
            ret.Roles = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_role>(roleIds);
            ret.RoleOrgs = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_role_org>(this.baseRepository.CommonRepository.GetApiParamByIds(roleIds), t => roleIds.Contains(t.role_id));
            return ret;
        }

        public async Task<List<MemberAuthModel>> GetRoleAuthByMemberIdsAsync(List<string> memberIds)
        {
            if (memberIds == null || !memberIds.Any())
            {
                return null;
            }

            List<MemberAuthModel> rets = new List<MemberAuthModel>();
            var model = await this.GetMemberAuthInfoModelAsync(memberIds);
            foreach (var item in memberIds)
            {
                var member = model.Members.FirstOrDefault(t => t.id == item);
                LibCheckNullUtils.CheckNull(member, "member");
                MemberAuthModel memberAuth = new MemberAuthModel
                {
                    MemberId = item
                };
                var tempRoleIds = model.MemberRoles.Where(t => t.member_id == item && t.org_id == member.org_id).Select(t => t.role_id).ToList();
                if (model.MemberRoleGroups.Any())
                {
                    var tempIds = model.MemberRoleGroups.Where(t => t.member_id == item && t.org_id == member.org_id).Select(t => t.role_group_id).ToList();
                    if (model.RoleGroupRoles != null && model.RoleGroupRoles.Any())
                    {
                        tempRoleIds.AddRange(model.RoleGroupRoles.Where(t => tempIds.Contains(t.role_group_id) && t.org_id == member.org_id).Select(t => t.role_id).ToList());
                    }
                }

                tempRoleIds = tempRoleIds.Distinct().ToList();
                foreach (var r in tempRoleIds)
                {
                    var role = model.Roles.FirstOrDefault(t => t.id == r);
                    RoleAuthModel roleM = new RoleAuthModel
                    {
                        RoleId = r,
                        FilterOrgType = role?.filter_org_type ?? 0
                    };
                    model.RoleAuthForms.Where(t => t.role_id == r).ForEach(t =>
                    {
                        RoleAuthFormModel form = new RoleAuthFormModel
                        {
                            FCPFormId = t.fcp_form_id
                        };
                        model.RoleAuthFormBtns.Where(t1 => t1.role_auth_form_id == t.id).ForEach(t2 =>
                        {
                            RoleAuthFormBtnModel btn = new RoleAuthFormBtnModel
                            {
                                BtnId = t2.btn_id
                            };
                            form.Btns.Add(btn);
                        });
                        model.RoleAuthFormFields.Where(t1 => t1.role_auth_form_id == t.id).ForEach(t2 =>
                        {
                            RoleAuthFormFieldModel field = new RoleAuthFormFieldModel
                            {
                                FieldId = t2.field_id
                            };
                            form.Fields.Add(field);
                        });
                        roleM.Forms.Add(form);
                    });
                    model.RoleAuthInfos.Where(t1 => t1.role_id == r).ForEach(t2 =>
                    {
                        RoleAuthInfoModel roleAuthInfoModel = new RoleAuthInfoModel();
                        roleM.AuthInfo = roleAuthInfoModel;
                    });

                    model.RoleOrgs.Where(t1 => t1.role_id == r).ForEach(t2 =>
                    {
                        roleM.RoleOrgIds.Add(t2.role_org_id);
                    });
                     
                    memberAuth.Roles.Add(roleM);
                }

                rets.Add(memberAuth);
            }

            return rets;
        }
    }
}
